FSM.H

//FSM.h
#ifndef FSM_H
#define FSM_H

#include <iostream>
#include <string>
#include <vector>
#include <memory>

class FSM;

//An individual state (must belong to a FSM)
//This is an abstract class and must be sub-classed
class FSMState
{
public:
  FSMState(){};
  FSMState(FSM *fsm){};
  virtual ~FSMState(){};
  virtual void Update(const float& dt) = 0;
  virtual void DoENTER(){};
  virtual void DoEXIT(){};

  std::string stateName;  //used to switch between states
  FSM *fsm;
};

//A vector of shared pointers housing all the states in the machine
typedef std::vector< std::tr1::shared_ptr<FSMState> > StateBank;

//---------------------------------------
//A Simple Finite State Machine
class FSM
{
public:
  FSM();
  ~FSM();
  void Update(const float& dt);

  void TransitionTo(std::string stateName);
  void DelayTransitionTo(std::string stateName);
  void AddState(FSMState *newState, bool makeCurrent);
  std::string GetState();

public:
  FSMState *currentState;
  std::string delayState;

   //Bank to house list of states
  StateBank stateBank;
  std::vector< std::tr1::shared_ptr<FSMState> >::iterator iter;
};

#endif

FSM.cpp

//FSM.cpp
#include "FSM.h"

//Constructor
FSM::FSM()
{
  currentState = NULL;
  delayState = "NONE";
}

//Destructor
FSM::~FSM()
{
  stateBank.clear();
}

//Update each tick
void FSM::Update(const float& dt)
{
  //Make sure a current state is loaded
  if (currentState == NULL) return;

  //Check if there are any delayed transition requests
  if (delayState != "NONE")
  {
    TransitionTo(delayState);
    delayState = "NONE";
  }

  //Update the current state, may trigger a transition.
  currentState->Update(dt);
}

//Called to transition to another state
//@param stateName the name of the state to transition to
void FSM::TransitionTo(std::string stateName)
{
  //Find the named state
  FSMState *goToState = NULL;
  for(iter= stateBank.begin(); iter!= stateBank.end(); iter++)
    if ( (*iter)->stateName == stateName )
      goToState = iter->get();

  //Error, trying to transition to a non-existant state
  if (goToState == NULL)
  {
    //Print an error here, or assert if you want
    return;
  }

  currentState->DoEXIT();
  goToState->DoENTER();
  currentState = goToState;
}

//Transition to another state (delayed until beginning of next update)
//@param stateName the name of the state to transition to
void FSM::DelayTransitionTo(std::string stateName)
{
  delayState = stateName;
}

//Add a state to the bank, optionally make it the current state
//@param newState the new state to add to the state machine
//@param makeCurrent is this new state the current state?
void FSM::AddState(FSMState *newState, bool makeCurrent)
{
  //Add this state to the FSM
  std::tr1::shared_ptr<FSMState> newStatePtr(newState);
  stateBank.push_back(newStatePtr);
  //Make this the current state?
  if (makeCurrent) currentState = newState;
}

//What is the name of the current state?
std::string FSM::GetState()
{
  return currentState->stateName;
}
